package ontprocessing_temp;

import java.io.InputStream;

import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.ontology.DatatypeProperty;
import com.hp.hpl.jena.ontology.ObjectProperty;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.ResultSetFormatter;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory.Interface;
import com.hp.hpl.jena.sparql.engine.binding.Binding;
import com.hp.hpl.jena.util.FileManager;

public class OntProcessor implements LayerConstant {

	public String inputFileName; 
    public OntModel ontModel; 

    public OntProcessor(){
    }
    
	public OntProcessor(String fileName){
		setInputFileName(fileName);
		ontModel=ontCreate(fileName);
	}
    
	public OntModel ontCreate(String aFile) {
	        OntModel model = ModelFactory.createOntologyModel();

	        InputStream in = FileManager.get().open(aFile);
	        if (in == null) {
	            throw new IllegalArgumentException( "File: " + aFile + " not found");
	        }
	        
	        // read the RDF/XML file
	        model.read(in, "");
	        
	        return model;
	}
	
	public int numResource(OntModel model,String queryPhrase){
		ResultSet results=rdfQuery(model,queryPhrase);
		int size=0;
		Binding binding=results.nextBinding();
		
		while (results.hasNext()){
			size++;
			binding=results.nextBinding();
		}
		return size;
	}
	
	public boolean existResourceNode(Node nd,OntModel model,String queryPhrase){
		Resource rs=model.createResource(nd.getURI());
		
		return existResource(rs,model,queryPhrase);
	}
	
	public boolean existResourceStr(String url,OntModel model,String queryPhrase){
		
		//Node nd=NodeCreateUtils.create(url);
		
		Resource rs = model.createResource(url);
		
		return existResource(rs,model,queryPhrase);
	}
	
	public boolean existResource(Resource rs,OntModel model,String queryPhrase){

		ResultSet results=rdfQuery(model,queryPhrase);
		
		return existResource(rs, results);
	}
	
	public boolean existResource(Resource rs, ResultSet results){
		boolean exist=false;
		
		Resource resource=null;
		String varName=(String) results.getResultVars().get(0);
		
		QuerySolution solution;
		//System.out.println(rs+"\n");
		while (results.hasNext()){
			solution=results.nextSolution();
			resource=solution.getResource(varName);
			//System.out.println(resource);
			if(resource.equals(rs)) {
				exist=true;
				break;
			}
		}
		//System.out.println(exist);
		return exist;
	}
	
	
	//update the data range with the new lowerBound
	/*
	public void ontLabelUpdate(Interface intf,float newLow, float upper, Resource lowerLabel,Resource upperLabel){

		String newLowerBound=new String();
		newLowerBound=String.valueOf((int)newLow);
		
		changeAvailableLabelSetLowerBound(intf,newLowerBound);
		//setUsedLabelSet(intf,lowerLabel);
	}
	*/
	/*
	public void changeAvailableLabelSetLowerBound(Interface intf, String lower){
		Resource labelSet;
		OntResource lso;
		Resource rs=intf.getResource();
		String layer=intf.getAtLayer();

		String availabelLabelSet=Layer.valueOf(layer).getPrefix()+":"+Layer.valueOf(layer).getASet();
	
        String s ="SELECT ?b ";
        String f="";
        String w=
        	"WHERE {" +
        	"<"+rs.getURI()+"> " +availabelLabelSet+" ?r."+
        	"?r collections:element ?b. "+
             "}"; 
        String queryPhrase=createQueryString(s,f,w);

        ObjectProperty lowerBound=ontModel.createObjectProperty(rootURL+"layer.owl#lowerBound");
        DatatypeProperty labelID=ontModel.createDatatypeProperty(rootURL+"layer.owl#label_ID");
        
        OntClass Label=ontModel.createClass(rootURL+"layer.owl#"+"Label");
        OntResource rs_lower=null;
		ResultSet results=rdfQuery(ontModel,queryPhrase);
		
		String element=(String) results.getResultVars().get(0);
		QuerySolution solution;
		Resource rs_ls=null;
		while (results.hasNext()){
			solution=results.nextSolution();
			labelSet=solution.getResource(element);
			String lowerURI=labelSet.getProperty(lowerBound).getResource().getURI().replaceAll("\\d+$", lower);
			Resource ls=ontModel.getResource(labelSet.getURI());
			ls.removeAll(lowerBound);
			rs_lower=ontModel.createOntResource(lowerURI);
			rs_lower.addRDFType(Label);
			rs_lower.addProperty(labelID, lower,XSDDatatype.XSDfloat);
			lso=ontModel.getOntResource(labelSet);
			lso.addProperty(lowerBound, rs_lower);
			System.out.println("------LabelSet----"+labelSet+":"+ls+ls.getProperty(lowerBound));
		}
		
	}
	*/
	public Resource getLabelResource(String uri,String id){
		String URI=uri.replaceAll("\\d+$", id);
		Resource label_rs=ontModel.createOntResource(URI);
	
		return label_rs;
	}
	
	//get availableLable Set
	/*
	public ResultSet getAvailableLabelSet(Interface intf){
		
		String rsURI=intf.getResource().getURI();
		String layer=intf.getAtLayer();
		String availableLabelSet=Layer.valueOf(layer).getPrefix()+":"+Layer.valueOf(layer).getASet();
		
		ResultSet results;
		
		
        String s ="SELECT ?lv ?uv ?l ?u ";
        String f="";
        String w=
        	"WHERE {" +
        	"<"+rsURI+"> " +availableLabelSet+" ?r."+
        	"?r collections:element ?b. "+
        	"?b layer:upperBound ?u. "+
        	"?u layer:label_ID ?uv. "+
        	"?b layer:lowerBound ?l. "+
        	"?l layer:label_ID ?lv"+
             "}"; 
        String queryPhrase=createQueryString(s,f,w);

        //System.out.println(queryPhrase);

		results=rdfQuery(ontModel,queryPhrase);
		
		return results;
	}
	*/
	/*
	public void setUsedLabelSet(Interface intf,Resource label){
		
		Resource ul;
		
		//System.out.println("okkkk----------"+intf.getURI());
		
		Property element=ontModel.createProperty(rootURL+"collections.owl#element");
		
		ResultSet results=getUsedLabelSet(intf);
		
		String layer=intf.getAtLayer();
		Resource rs=intf.getResource();
		String ob=intf.getUri()+"/"+Layer.valueOf(layer).getUSet();
		if(!results.hasNext()){
			Property usedLabelSet=ontModel.createProperty(rootURL+"layer.owl#"+Layer.valueOf(layer).getUSet());
			ul=ontModel.createResource(ob);
			rs.addProperty(usedLabelSet, ul);
		}
		else{
			ul=results.nextSolution().getResource((String) results.getResultVars().get(0));	
			System.out.println(ul+":"+element+":"+label);
		}
		
		if(label!=null) ul.addProperty(element, label);
		System.out.println("---Used Label:"+intf.getURI()+ul.getProperty(element));
		
	}
	*/
	/*
	public ResultSet getUsedLabelSet(Interface intf){
		ResultSet results;
		String layer=intf.getAtLayer();
		String usedLabelSet=Layer.valueOf(layer).getPrefix()+":"+Layer.valueOf(layer).getUSet();
		
        String s ="SELECT ?b ";
        String f="";
        String w=
        	"WHERE {" +
        	"<"+intf.getURI()+"> " +usedLabelSet+" ?r."+
        	"?r collections:element ?b. "+
             "}"; 
        String queryPhrase=createQueryString(s,f,w);
System.out.println(queryPhrase);
		results=rdfQuery(ontModel,queryPhrase);
				
		return results;
	
	}
	*/
	//get layer:Layer 	
	public ResultSet getLayer(String rsURI){

        String s ="SELECT ?r ";
        String f="";
        String w=
        	"WHERE {" +
        	"<"+rsURI+">" +" ?p ?r."+
        	" ?r rdf:type "+ "layer:Layer" +
        	"      }"; 
        String queryPhrase=createQueryString(s,f,w);
        
		ResultSet results=rdfQuery(ontModel,queryPhrase);
		
		return results;
	}
	
	//get layer:AdapatationProperty 	
	public ResultSet getLayerAdapatation(String rsURI){

        String s ="SELECT ?r ";
        String f="";
        String w=
        	"WHERE {" +
        	"<"+rsURI+">" +" ?p ?r."+
        	" ?p rdf:type "+ "layer:AdaptationProperty" +
        	"      }"; 
        String queryPhrase=createQueryString(s,f,w);

		ResultSet results=rdfQuery(ontModel,queryPhrase);
		
		return results;
	}

	public ResultSet getSwitchedToInterface(String rsURI){
		
	     String selectStr = "SELECT ?intf ?intf_peer ?c ";
	        String fromStr="";
	        String whereStr=
	        	"WHERE {" +
	        	"?p a layer:AdaptationProperty. "+
	        	"<"+rsURI+">" + " ndl:hasInterface ?intf. "+
	        	"?intf ndl:connectedTo ?intf_peer." + 
	        	"?intf ?p ?a."+
	        	"?intf_peer ndl:inConnection true."+
	        	"?intf_peer ?l ?r."+
	        	"?r rdf:type layer:Layer."+
	        	"?intf_peer ndl:interfaceOf ?b."+
	        	"?b ndl:hasSwitchMatrix ?sw. "+
	        	"?sw layer:switchingCapability ?c"+
	        	"      }";
			
			String queryPhrase=createQueryString(selectStr, fromStr, whereStr);
			
			ResultSet results=rdfQuery(ontModel,queryPhrase);
			
			return results;
		
	}
	
	public ResultSet getSwitchedToAdaptation(String rsURI){
		
	     String selectStr = "SELECT ?intf ?intf_peer ?c ";
	        String fromStr="";
	        String whereStr=
	        	"WHERE {" +
	        	"?p a layer:AdaptationProperty. "+
	        	"<"+rsURI+">" + " ndl:hasInterface ?intf. "+
	        	"?intf ndl:connectedTo ?intf_peer." + 
	        	"?intf ?p ?a."+
	        	"?intf_peer ndl:inConnection true."+
	        	"?intf_peer ?l ?r."+
	        	"?r rdf:type layer:Layer."+
	        	"?intf_peer ndl:interfaceOf ?b."+
	        	"?b ndl:hasSwitchMatrix ?sw. "+
	        	"?sw layer:switchingCapability ?c"+
	        	"      }";
			
			String queryPhrase=createQueryString(selectStr, fromStr, whereStr);
			
			ResultSet results=rdfQuery(ontModel,queryPhrase);
			
			return results;
		
	}
	
	public ResultSet getConnectionSubGraphSwitchedTo(String url,String url2){
		url="https://geni-orca.renci.org/owl/ben.rdf#Duke/Polatis";
		url2="https://geni-orca.renci.org/owl/ben.rdf#Duke/Infinera/DTN";	
	    String s ="SELECT ?p ?a ?b ?c ";
	    String f="";
	    String w=
	        	"WHERE {" +
	        	"?p a layer:AdaptationProperty."+
	        	"(<"+url+"> '[ndl:hasInterface]+/[ndl:connectedTo]+"+"/[wdm:OCG]*/[wdm:WDM]*"+"/[layer:switchedTo]+/[ndl:interfaceOf]*)+' <"+url2+">) gleen:Subgraph (?a ?b ?c)"+
	        	"      }";
        		
		String queryPhrase=createQueryString(s,f,w);
        
        System.out.println(queryPhrase);
        
        ResultSet results=rdfQuery(ontModel,queryPhrase);
       
        //outputQueryResult(results);
        
        return results;
		
	}
	
	
	//Get the subgraph between two directly connected devices
	public ResultSet getSubGraphLinkTo(String url1, String url2){
        String s ="SELECT ?a ?b ?c ";
        String f="";
        String w=
        	"WHERE {" +
        	"(<"+url1+"> '[ndl:hasInterface]+/([ndl:hasInputInterface]|[ndl:hasOutputInterface])*/([ndl:linkTo]|[ndl:connectedTo])+/[ndl:interfaceOf]+' <"+url2+">) gleen:Subgraph (?a ?b ?c)"+
        	"      }";
        
        String queryPhrase=createQueryString(s,f,w);
        
        //System.out.println(queryPhrase);
        
        ResultSet results=rdfQuery(ontModel,queryPhrase);
        
        //outputQueryResult(results);
        
        return results;
		
	}
	
//	Get the subgraph between two directly connected devices
	public ResultSet getSubGraphConnectedTo(String url1, String url2){
        String s ="SELECT ?a ?b ?c ";
        String f="";
        String w=
        	"WHERE {" +
        	"(<"+url1+"> '[ndl:hasInterface]+/[ndl:connectedTo]+/[ndl:interfaceOf]+' <"+url2+">) gleen:Subgraph (?a ?b ?c)"+
        	"      }";
        String queryPhrase=createQueryString(s,f,w);
        
        //System.out.println(queryPhrase);
        
        ResultSet results=rdfQuery(ontModel,queryPhrase);
        
        //outputQueryResult(results);
        
        return results;
		
	}
	    
    public String createQueryStringObject(String p){
        String selectStr = "SELECT ?ob ";
        String fromStr="";
        String whereStr=
        	"WHERE {" +
        	"?resource "+ p + " ?ob"+
        	"      }";
    	return createQueryString(selectStr, fromStr, whereStr);
    }
    
    public String createQueryStringSubject(String p, String ob){
        String selectStr = "SELECT ?resource";
        String fromStr="";
        String whereStr=
        	" WHERE {" +
        	"?resource "+ p + " <"+ob+">"+
        	"    }";
    	return createQueryString(selectStr, fromStr, whereStr);
    }    
    
    public String createQueryStringSubjectData(String p, String ob){
        String selectStr = "SELECT ?resource";
        String fromStr="";
        String whereStr=
        	" WHERE {" +
        	"?resource "+ p +" "+ob+
        	"    }";
    	return createQueryString(selectStr, fromStr, whereStr);
    }    
 
    public String getInputFileName() {
		return inputFileName;
	}

	public void setOntModel(OntModel ontModel) {
		this.ontModel = ontModel;
	}

	public String createQueryStringObject(String sb,String p){
        String selectStr = "SELECT ?object ";
        String fromStr="";
        String whereStr=
        	"WHERE {<" +
        	sb+"> "+p+" ?object"+
        	"      }";
    	return createQueryString(selectStr, fromStr, whereStr);
    }    
    
    
    public String createQueryStringType(String ob){
        String selectStr = "SELECT ?resource ";
        String fromStr="";
        String whereStr=
        	"WHERE {" +
        	"?resource a " +ob+
        	"      }";
    	return createQueryString(selectStr, fromStr, whereStr);
    }
  
    public String createQueryStringConnect(){
        String selectStr = "SELECT ?resource ?object ";
        String fromStr="";
        String whereStr=
        	"WHERE {" +
        	"?resource "+"ndl:connectedTo "+"?object"+
        	"      }";
    	return createQueryString(selectStr, fromStr, whereStr);
    }
    
    public String createQueryStringConnectClass(String ob){
        String selectStr = "SELECT ?resource ?object ";
        String fromStr="";
        String whereStr=
        	"WHERE {" +
        	"?resource a " +ob+"."+
        	"?resource "+"ndl:connectedTo "+"?object"+
        	"      }";
    	return createQueryString(selectStr, fromStr, whereStr);
    }
   
    
    public String createQueryStringProperty(String subject,String pr, String sub, boolean subPath){
        String selectStr = "SELECT ?object ";
        String fromStr="";
        String whereStr;
        if(!subPath) 
        	whereStr=
        		"WHERE {" + "<"+
        			subject +"> " + pr + " ?object"+
        				"      }";
        else
        	whereStr=
        		"WHERE {" + "<" 
        		    +subject +"> " + 
        			pr + sub +
        			" ?object"+ ")."+
			"      }";
        		
    	return createQueryString(selectStr, fromStr, whereStr);
    }
    
    public String createQueryString(String selectStr,String fromStr, String whereStr){
    	String queryString=ontPrefix+selectStr+fromStr+whereStr;
    	return queryString;
    }
    
    public Query createQuery(String queryString){
    	return QueryFactory.create(queryString);
    }
   

	public ResultSet rdfQuery(OntModel model, String queryString) {

        Query query = QueryFactory.create(queryString);

//      Execute the query and obtain results
        QueryExecution qe = QueryExecutionFactory.create(queryString, model);
        ResultSet results = qe.execSelect();	
        
        return results;
	}
	
//  Output query results	
	public void outputQueryResult(ResultSet results,Query query){
		ResultSetFormatter.out(System.out, results, query);	
	}
	
	public void outputQueryResult(ResultSet results){
		ResultSetFormatter.out(System.out, results);	
	}
	
	
	public OntResource addResource(String URI) {
		return ontModel.createOntResource(URI);
		
	}
	
	public void addProperty(OntResource aResource,Property aProperty, RDFNode aObject){
		aResource.addProperty(aProperty,aObject);
	}

    public void setInputFileName(String aName){
    	inputFileName=aName;
    }
	
	public OntModel getOntModel(){
		return ontModel;
	}
}
